package com.springcloud.gateway.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.springcloud.gateway.props.AuthProperties;
import com.springcloud.gateway.provider.AuthProvider;
import com.springcloud.gateway.provider.RequestProvider;
import com.springcloud.gateway.provider.ResponseProvider;
import com.springcloud.gateway.util.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * @version V1.0
 * @Author 宋聚智
 * @Date 2019/10/31 14:52
 * @description
 * @Modify By：
 * @ModifyTime： 2019/10/31
 * @Modify marker：
 **/
//鉴权认证
    @Component
    @Slf4j
    @AllArgsConstructor
public class AuthFilter implements GlobalFilter, Ordered {

    private AuthProperties authProperties;
    private ObjectMapper objectMapper;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String orignalRequestUrl= RequestProvider.getOriginalRequesetUrl(exchange);
        String path= exchange.getRequest().getURI().getPath();
        if(isSkip(path)|| isSkip(orignalRequestUrl)){
            return chain.filter(exchange);
        }
        ServerHttpResponse resp=  exchange.getResponse();
        String headerToken= exchange.getRequest().getHeaders().getFirst(AuthProvider.AUTH_KEY);
        String paramToken= exchange.getRequest().getQueryParams().getFirst(AuthProvider.AUTH_KEY);
        if(StringUtils.isAllBlank(headerToken,paramToken)){
            return unAuth(resp,"令牌缺失，鉴权失败");
        }
        String auth= StringUtils.isBlank(headerToken)?paramToken:headerToken;
        String token= JwtUtil.getToken(auth);
        Claims claims= JwtUtil.parseJWT(token);
        if(claims==null){
            return  unAuth(resp,"请求未授权");
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100;
    }

    private Boolean isSkip(String path){
        return AuthProvider.getDefaultSkipUrl().stream().
                map(url->url.replace(AuthProvider.TARGET,AuthProvider.REPLACEMENT))
                .anyMatch(path::startsWith)
                ||
                authProperties.getSkipUrl().stream().map(url -> url.replace(AuthProvider.TARGET, AuthProvider.REPLACEMENT)).anyMatch(path::startsWith);

    }


    public Mono<Void> unAuth(ServerHttpResponse resp,String msg){
        resp.setStatusCode(HttpStatus.UNAUTHORIZED);
        resp.getHeaders().add("content-Type","application/json:charset=UTF-8");
        String result="";
        try{
            result =objectMapper.writeValueAsString(ResponseProvider.unAuth(msg));
        }catch (JsonProcessingException e){

        }
        DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
        return resp.writeWith(Flux.just(buffer));
    }
}
